﻿using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Security.Cryptography;
using System.Text;
using TY.UC.Common.Extension;

namespace TY.UC.Common
{
    /// <summary>
    /// 加密工具类
    /// </summary>
    public class Security
    {
        public static string HmacSHA256(string message, string secret)
        {
            secret = secret ?? "";
            var encoding = new System.Text.UTF8Encoding();
            byte[] keyByte = encoding.GetBytes(secret);
            byte[] messageBytes = encoding.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                return Convert.ToBase64String(hashmessage);
            }
        }
        /// <summary>
        /// SHA1 加密
        /// </summary>
        public static string Sha1(string source)
        {
            if (string.IsNullOrEmpty(source)) return null;
            var encoding = Encoding.UTF8;
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            return HashAlgorithmBase(sha1, source, encoding);
        }
        /// <summary>
        /// HashAlgorithm 加密统一方法
        /// </summary>
        private static string HashAlgorithmBase(HashAlgorithm hashAlgorithmObj, string source, Encoding encoding)
        {
            byte[] btStr = encoding.GetBytes(source);
            byte[] hashStr = hashAlgorithmObj.ComputeHash(btStr);
            return hashStr.Bytes2Str();
        }
        
        /// <summary>
        /// Aes加密
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="key">aes密钥，长度必须32位</param>
        /// <returns>加密后的字符串</returns>
        public static string AESEncrypt(string source, string key)
        {
            using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
            {
                aesProvider.Key = UTF8Encoding.UTF8.GetBytes(key); //GetAesKey(key);固定32位秘钥方法
                aesProvider.Mode = CipherMode.ECB;
                aesProvider.Padding = PaddingMode.PKCS7;
                using (ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor())
                {
                    byte[] inputBuffers = Encoding.UTF8.GetBytes(source);
                    byte[] results = cryptoTransform.TransformFinalBlock(inputBuffers, 0, inputBuffers.Length);
                    aesProvider.Clear();
                    aesProvider.Dispose();
                    return Convert.ToBase64String(results, 0, results.Length);
                }
            }
        }
        /// <summary>
        ///  AES 加密
        /// </summary>
        /// <param name="str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AesEncrypt(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);

            System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
            {
                Key = Encoding.UTF8.GetBytes(key),
                Mode = System.Security.Cryptography.CipherMode.ECB,
                Padding = System.Security.Cryptography.PaddingMode.PKCS7
            };

            System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }
        /// <summary>
        ///  AES 解密
        /// </summary>
        /// <param name="str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AesDecrypt(string str, string key)
        {
            try
            {
                if (string.IsNullOrEmpty(str)) return null;
                Byte[] toEncryptArray = Convert.FromBase64String(str); 
                System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
                {
                    Key = Encoding.UTF8.GetBytes(key),
                    Mode = System.Security.Cryptography.CipherMode.ECB,
                    Padding = System.Security.Cryptography.PaddingMode.PKCS7
                }; 
                System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateDecryptor();
                Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); 
                return Encoding.UTF8.GetString(resultArray);
            }
            catch(Exception ex)
            {
                throw ex;
            } 
        }
        /// <summary>
        /// RSA加密
        /// </summary>
        /// <param name="xmlPublicKey">公钥</param>
        /// <param name="m_strEncryptString">MD5加密后的数据</param>
        /// <returns>RSA公钥加密后的数据</returns>
        public static string RSAEncrypt(string xmlPublicKey, string content)
        {
            string str2;
            try
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(xmlPublicKey);
                byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(content);
                str2 = Convert.ToBase64String(provider.Encrypt(bytes, false));
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return str2;
        }
       /// <summary>
       /// RSA加密
       /// </summary>
       /// <param name="source">需要加密的数据</param>
       /// <param name="publicKey">公钥</param>
       /// <returns></returns>
        public static string Rsa(string source,string publicKey)
        { 
            string _key = RSAKeyConvert.RSAPublicKeyJava2DotNet(publicKey);
            try
            { 
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
                rsa.FromXmlString(_key); 
                var cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(source), true);
                return Convert.ToBase64String(cipherbytes);
            }
            catch(Exception ex)
            {
                throw ex;
            } 
        }
        /// <summary>  
        /// RSA加密  
        /// </summary>  
        /// <param name="publicKeyJava"></param>  
        /// <param name="data"></param>  
        /// <returns></returns>  
        public static string EncryptJava(string publicKeyJava, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            string xmlpublicKey = ConvertToXmlPublicJavaKey(publicKeyJava);
            provider.FromXmlString(xmlpublicKey);//加载公钥  

            cipherbytes = provider.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);

            return Convert.ToBase64String(cipherbytes);
        }
        /// <summary>  
        /// 把java的公钥转换成.net的xml格式  
        /// </summary>  
        /// <param name="privateKey">java提供的第三方公钥</param>  
        /// <returns></returns>  
        public static string ConvertToXmlPublicJavaKey(string publicJavaKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicJavaKey));
            string xmlpublicKey = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
              Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
              Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
            return xmlpublicKey;
        }
        /// <summary>  
        /// RSA解密  
        /// </summary>  
        /// <param name="privateKeyJava"></param>  
        /// <param name="content"></param>  
        /// <returns></returns>  
        public static string DecryptJava(string privateKeyJava, string data, string encoding = "UTF-8")
        {
            try
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                byte[] cipherbytes;
                string xmlPrivateKey = ConvertToXmlPrivateKey(privateKeyJava);
                provider.FromXmlString(xmlPrivateKey);//加载私钥  

                cipherbytes = provider.Decrypt(Convert.FromBase64String(data), false);

                return Encoding.GetEncoding(encoding).GetString(cipherbytes);
            }
            catch(Exception ex)
            {
                throw ex;
            } 
        }
        /// <summary>
        /// RSA解密
        /// </summary>
        public static string UnRsa(string source,string key)
        {
            string _key = ConvertToXmlPrivateKey(key);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(_key);
            var cipherbytes = rsa.Decrypt(Convert.FromBase64String(source), true);
            return Encoding.UTF8.GetString(cipherbytes);
        }
        /// <summary>
        /// RSA签名算法为"SHA1WithRSA"
        /// </summary>
        /// <param name="data"></param>
        /// <param name="privateKeyJava"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string SignSHA1WithRSAData(string data, string privateKeyJava, string encoding = "UTF-8")
        {
            string _key = ConvertToXmlPrivateKey(privateKeyJava); 
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); 
            provider.FromXmlString(_key);//加载私钥  
            var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
            byte[] signatureBytes = provider.SignData(dataBytes, new SHA1CryptoServiceProvider());
            return Convert.ToBase64String(signatureBytes);
        }
        /// <summary>  
        ///  把java的私钥转换成.net的xml格式  
        /// </summary>  
        /// <param name="rsa"></param>  
        /// <param name="privateJavaKey">java提供的第三方私钥</param>  
        /// <returns></returns>  
        public static string ConvertToXmlPrivateKey(string privateJavaKey)
        {
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateJavaKey));
            string xmlPrivateKey = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
                         Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
            return xmlPrivateKey;
        }
        /// <summary>
        /// RSA验签：算法"SHA1WithRSA"
        /// </summary>
        /// <param name="data">原数据</param>
        /// <param name="publicKeyJava">公钥</param>
        /// <param name="signature">签名数据</param>
        /// <param name="encoding">编码格式</param>
        /// <returns></returns>
        public static bool VerifyJava(string data, string publicKeyJava, string signature, string encoding = "UTF-8")
        {
            string xmlpublicKey = ConvertToXmlPublicJavaKey(publicKeyJava);
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            //导入公钥，准备验证签名   
            provider.FromXmlString(xmlpublicKey);//加载公钥  
             //返回数据验证结果  
            byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
            byte[] rgbSignature = Convert.FromBase64String(signature); 
            return provider.VerifyData(Data, new SHA1CryptoServiceProvider(), rgbSignature); 
        }
        /// <summary>
        /// RSA签名 算法MD5
        /// </summary>
        /// <param name="strKeyPrivate">私钥</param>
        /// <param name="strHashbyteSignature">待签名Hash描述</param>
        /// <param name="strEncryptedSignatureData">签名后的结果</param>
        /// <returns></returns>
        public string SignMD5RSAData(string strKeyPrivate, string content)
        {
            string sgin = "";
            try
            {

                byte[] HashbyteSignature;
                byte[] EncryptedSignatureData;
                HashbyteSignature = Convert.FromBase64String(content);
                System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
                RSA.FromXmlString(strKeyPrivate);
                System.Security.Cryptography.RSAPKCS1SignatureFormatter RSAFormatter = new System.Security.Cryptography.RSAPKCS1SignatureFormatter(RSA);
                //设置签名的算法为MD5 
                RSAFormatter.SetHashAlgorithm("MD5");
                //执行签名 
                EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
                sgin = Convert.ToBase64String(EncryptedSignatureData);
                return sgin;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        
    }
}
